iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 27
0
Modern Web

先你一步的菜鳥 - 從 0 開始的前端網頁設計系列 第 27

Day-27 使用 hook 打造專屬 blog(12) - 搭配 Redux 整理資料流

  • 分享至 

  • xImage
  •  

嗨大家好我是 Chris,今天這篇將稍微解釋一下甚麼是 redux 以及它的運作方式和他能怎麼改我們的資料流,那話不多說就馬上開始吧。

首先需要聲明,在之前釋出的 hook api 中也有一個跟 Redux 相似的 api React Redux,讓 Hook 也可以作用在 Redux app 上,所以這兩者是不衝突的,細節我也還沒研究,不過感覺也是相當不錯的,而且兩者觀念基本上相同,如果對 React Redux 有興趣的先學 Redux 也不錯喔。

Redux

「The Single Immutable State Tree」- Redux 開發者是這麼說的,也就是單向不可變動的樹狀資料。

三大原則

Redux 有 3 大原則,讓資料可以被更輕鬆的管理。

  • 整個專案的 State 都將被放在同一個儲存庫 (Store)

  • 你不能直接改變存放在 Store 的資料,相對的,你可以發出一個請求 (Action), 也就是描述事件狀態的物件,讓 Redux 改變 State。

  • 改變 State 的方式是 pure function,也就是說你不能直接改變傳進來的參數,而是透過 Reducer 取得先前的 state 去建立一個新的 object 並回傳這個物件。

註:其實硬要的話,你還是改的掉之前的 state,不過不要啦,因為這跟 Redux 的設計有關,直接更改很可能會造成出錯。而且這可以保證你的改變都是有跡可循的,不會因為 web requset 或是不預期的 state change 造成意外的 bug 。

你可能會說,限制這麼多才不好吧,nono,有一句話叫做絕對的自制就是絕對的自由

就跟我很久前介紹過的 ESlint 一樣,透過合理的格式約束,可以減少錯誤的發生。

三大物件

在 react 裡,絕大部分的動作都是透過這 3 大物件所運行的,以下將一一介紹:

Action

也就是描述狀態的物件,基本上所有對資料的動作都會通過 Action ,它必定會含有 type 這個屬性,用來對應發送這個 Action 要做的動作,如果我們需要實作一個計數器的話,Action 會像這樣:

// action example
  {
      type: 'add',
      list:'My first thing',
    }

而 type 通常會把字串存進常數來使用他,也是為了方便,以後更新的話就不用一個一個去找了:

const ADD_LIST = 'add'

  {
      type: ADD_list,
      list: 'My first thing',
    }

除了 type 之外 Action 其他的設計都取決於你。

Action Creator

當然我們總不可能每次需要請求 State 時都臨時想好我們的資料結構,所以會有一個專門用來產出 Action 的 function ,並回傳回來:

  function add(list){
    return{
      type: ADD_LIST,
      list,
    }
  }

而這時我們就可以通過呼叫 dispatch() 傳達 Action 給 Store ,藉由比對 type 執行對應的 Reducer ,就可以得到我們想要的 State 了。

Reducer

Reducer 在前面三大原則中說過,是一個 pure function ,用來處理 Action.type 對應的動作,他不會改變先前傳過來的 state,注意,這邊說的是 pure function,所以你也不能在裡面執行會造成改變其他 state 的動作(side effect),也不能使用 date.now()Math.random() 等等會產生新 state 的 function。

註: 複習一下,pure function 就是你丟進去甚麼,就只能產出甚麼,其他的在 Day-8 有提過。

所以按照我們的需求,Reducer 會長這樣:

initialState:{
List:[]
}

function AddList(state = initialState, action) {
  switch (action.type) {
    case ADD_list:
      return { ...state,List:action.list };
    default :
      return initialState
}

可以看到我們不會改變先前的 state ,而是採用 Object Spread (...) 拆分state並重新組裝它

且可以使用 Switch case 讓 type 對應到實際的動作,如果都沒有符合,就會回傳 initialState。

而如果你有複數的 Reducer 的話,可以使用 combineReducers() 來合併 app,並 export 到 store 讓我們可以使用他,像這樣:

const Reducers = combineReducers({
  AddList,
  fun1,
 Fun2,
 Fun3,
})

Export default Reducers;

Store

Store 是把 Action 和 Reducer 集合起來管理的物件,整個專案只會有一個 Store。

我們可以藉由 createStore() 來創建 Store:

const store = createStore(Reducers);

Store 有 3 個參數接口

  • reducer (Function):接收當下的 state tree 和要處理的 action 的邏輯區塊。
  • preloadedState (any) :非必要,初始的 state,需要可以符合接收 reducer 回傳的格式。
  • enhancer(Function):非必要,可以使用第三方功能加強 store,例如 middleware 。

store 可以使用 dispatch 傳送 action :

Dispatch(AddList('My first thing'))

且可以使用 getState() 來讀取當下 state tree 的狀態

Console.log( getState() ) 

// object {List:"My first thing"}

所以整個過程會像這樣:

https://ithelp.ithome.com.tw/upload/images/20200927/20123396ak8ShSGdrx.png
圖片來源

以上是 redux 的基本架構與運作方法,明天將會帶到如何將 Redux 應用到 React 專案中。

本篇文章參考自 => https://chentsulin.github.io/redux/docs/introduction/


上一篇
Day-26 使用 hook 打造專屬 blog(11) - Code Notes(2)
下一篇
Day-28 使用 hook 打造專屬 blog(13) - Redux 實作(搭配 connect provider)
系列文
先你一步的菜鳥 - 從 0 開始的前端網頁設計31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言